#!/bin/bash

# ================== 配置区 ==================
MAX_JOBS=4
DOWNLOAD_DIR="./downloads"
LIST_FILE="download.txt"
LOG_FILE="download.log"
SKIP_EXISTING=true
# ===========================================

mkdir -p "$DOWNLOAD_DIR"

if [[ ! -f "$LIST_FILE" ]]; then
    echo "错误：$LIST_FILE 不存在！"
    exit 1
fi

# 读取非空行
mapfile -t TASK_LINES < <(grep -v '^[[:space:]]*$' "$LIST_FILE")
total=${#TASK_LINES[@]}

if (( total == 0 )); then
    echo "警告：下载列表为空。"
    exit 0
fi

# 创建 FIFO 控制并发
FIFO="/tmp/parallel_dl_fifo_$$"
mkfifo "$FIFO"
exec 3<>"$FIFO"
rm -f "$FIFO"

for ((i=0; i<MAX_JOBS; i++)); do
    echo >&3
done

# 用于进度和日志的锁和计数文件
LOCK_FILE="/tmp/parallel_dl_lock_$$"
COUNTER_FILE="/tmp/parallel_dl_counter_$$"
echo 0 > "$COUNTER_FILE"

# 安全日志写入
log_msg() {
    local msg="$1"
    (
        flock -x 200
        echo "$msg" >> "$LOG_FILE"
    ) 200>"$LOCK_FILE"
}

# 原子递增并获取当前序号
get_next_index() {
    (
        flock -x 200
        local n=$(cat "$COUNTER_FILE")
        n=$((n + 1))
        echo "$n" > "$COUNTER_FILE"
        echo "$n"
    ) 200>"$LOCK_FILE"
}

# 安全构造 wget 命令（避免 sed 分隔符冲突）
build_wget_cmd() {
    local orig_cmd="$1"
    local dir="$2"
    # 使用 awk 重构命令：在 wget 后插入 -P 'dir'
    echo "$orig_cmd" | awk -v d="$dir" '
    {
        for(i=1; i<=NF; i++) {
            if($i == "wget") {
                printf "wget -P %s ", d
            } else {
                printf "%s ", $i
            }
        }
        print ""
    }'
}

download_task() {
    local orig_cmd="$1"

    # 提取 URL（取最后一个双引号内容）
    local url=$(echo "$orig_cmd" | grep -o '"[^"]*"$' | tr -d '"')
    [[ -z "$url" ]] && url=$(echo "$orig_cmd" | awk '{print $NF}' | tr -d '"')
    local filename=$(basename "$url" 2>/dev/null || echo "unknown")
    local target="$DOWNLOAD_DIR/$filename"

    # 获取令牌
    read -u 3

    # 跳过已存在
    if [[ "$SKIP_EXISTING" == "true" ]] && [[ -f "$target" ]]; then
        local idx=$(get_next_index)
        local now=$(date '+%Y-%m-%d %H:%M:%S')
        echo "[$idx/$total] ⏭️ $filename （已存在）"
        log_msg "$now | $filename | ⏭️ 跳过（文件已存在）"
        echo >&3
        return 0
    fi

    # 构造新命令（安全处理路径）
    local new_cmd
    new_cmd=$(build_wget_cmd "$orig_cmd" "$DOWNLOAD_DIR")

    # 执行
    if eval "$new_cmd"; then
        local status="✅ 成功"
        local emoji="✅"
    else
        local status="❌ 失败"
        local emoji="❌"
    fi

    local idx=$(get_next_index)
    local now=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$idx/$total] $emoji $filename"
    log_msg "$now | $filename | $status"

    # 释放令牌
    echo >&3

    # 最后一个任务完成时提示
    if (( idx == total )); then
        local final_msg="$now | 🎉 全部下载完成！共 $total 个任务。"
        echo -e "\n$final_msg"
        log_msg "$final_msg"
    fi
}

# 导出函数和变量
export -f download_task log_msg get_next_index build_wget_cmd
export DOWNLOAD_DIR LOG_FILE LOCK_FILE COUNTER_FILE SKIP_EXISTING

# 启动任务
for line in "${TASK_LINES[@]}"; do
    line=$(echo "$line" | xargs)
    [[ -n "$line" ]] && download_task "$line" &
done

wait

# 清理
exec 3>&-
rm -f "$LOCK_FILE" "$COUNTER_FILE"

echo "🔚 脚本执行结束。日志：$LOG_FILE"
